package main

import (
	"fmt"
	"sort"
	"strings"
)

func main() {
	// ==========================================
	// 数组 (Arrays)
	// ==========================================

	// 声明并初始化数组
	var numbers [5]int                    // 声明一个包含5个整数的数组，默认值为0
	fruits := [3]string{"苹果", "香蕉", "橙子"} // 声明并初始化

	// 使用...让编译器计算数组长度
	colors := [...]string{"红", "绿", "蓝", "黄", "紫"}

	// 指定索引的初始化
	directions := [4]string{0: "北", 1: "东", 2: "南", 3: "西"}
	sparse := [10]int{1: 10, 4: 40, 9: 90} // 其他元素为默认值0

	// 访问数组元素
	numbers[0] = 100
	numbers[1] = 200

	// 获取数组长度
	fmt.Printf("fruits数组的长度: %d\n", len(fruits))

	// 遍历数组
	fmt.Println("遍历数组:")
	for i := 0; i < len(colors); i++ {
		fmt.Printf("colors[%d] = %s\n", i, colors[i])
	}

	// 使用range遍历
	fmt.Println("\n使用range遍历数组:")
	for index, value := range directions {
		fmt.Printf("directions[%d] = %s\n", index, value)
	}

	// 如果只需要值，可以使用_忽略索引
	fmt.Println("\n只获取数组值:")
	for _, fruit := range fruits {
		fmt.Println(fruit)
	}

	// 数组是值类型，赋值会创建副本
	a := [3]int{1, 2, 3}
	b := a // b是a的副本
	b[0] = 100
	fmt.Printf("a: %v\n", a) // a不变: [1 2 3]
	fmt.Printf("b: %v\n", b) // b改变: [100 2 3]

	// 多维数组
	matrix := [3][3]int{
		{1, 2, 3},
		{4, 5, 6},
		{7, 8, 9},
	}

	fmt.Println("\n二维数组:")
	for i := 0; i < 3; i++ {
		for j := 0; j < 3; j++ {
			fmt.Printf("%d ", matrix[i][j])
		}
		fmt.Println()
	}

	// 打印所有数组
	fmt.Printf("\nnumbers: %v\n", numbers)
	fmt.Printf("fruits: %v\n", fruits)
	fmt.Printf("colors: %v\n", colors)
	fmt.Printf("directions: %v\n", directions)
	fmt.Printf("sparse: %v\n", sparse)

	// ==========================================
	// 切片 (Slices)
	// ==========================================

	// 声明切片
	var emptySlice []int             // 声明一个空切片，nil切片
	integers := []int{1, 2, 3, 4, 5} // 使用字面量创建切片
	// 使用make创建切片
	// make([]T, length, capacity)
	// 长度为5，容量为5的切片
	buffer := make([]byte, 10, 20) // 长度为10，容量为20的切片

	// 切片的长度和容量
	fmt.Printf("\n切片integers的长度: %d, 容量: %d\n", len(integers), cap(integers))
	fmt.Printf("切片buffer的长度: %d, 容量: %d\n", len(buffer), cap(buffer))

	// nil切片
	fmt.Printf("emptySlice是否为nil: %t\n", emptySlice == nil)

	// 空切片
	emptyButNotNil := []int{}
	fmt.Printf("emptyButNotNil是否为nil: %t\n", emptyButNotNil == nil)

	// 从数组创建切片
	array := [5]int{10, 20, 30, 40, 50}
	slice1 := array[1:4] // 包含索引1,2,3的元素
	fmt.Printf("slice1: %v\n", slice1)

	// 切片语法 [low:high:max]
	// low: 起始索引（包含）
	// high: 结束索引（不包含）
	// max: 容量结束索引
	slice2 := array[1:4:5] // 长度为3，容量为4的切片
	fmt.Printf("slice2长度: %d, 容量: %d\n", len(slice2), cap(slice2))

	// 切片是引用类型，多个切片可以共享底层数组
	slice3 := array[:]
	slice3[0] = 100
	fmt.Printf("修改slice3后的array: %v\n", array) // array也会改变

	// 切片的切片
	slice4 := slice3[1:3]
	fmt.Printf("slice4: %v\n", slice4)

	// 追加元素
	integers = append(integers, 6)
	integers = append(integers, 7, 8, 9) // 可以一次追加多个元素
	fmt.Printf("追加后的integers: %v\n", integers)

	// 追加一个切片到另一个切片
	moreIntegers := []int{10, 11, 12}
	integers = append(integers, moreIntegers...) // 注意...语法
	fmt.Printf("追加切片后的integers: %v\n", integers)

	// 切片的复制
	src := []int{1, 2, 3}
	dst := make([]int, len(src))
	copied := copy(dst, src)
	fmt.Printf("复制的元素个数: %d, dst: %v\n", copied, dst)

	// 删除切片中的元素（通过重新切片）
	// 删除索引为2的元素
	s := []int{1, 2, 3, 4, 5}
	s = append(s[:2], s[3:]...)
	fmt.Printf("删除后的切片: %v\n", s)

	// 在切片中间插入元素
	s = []int{1, 2, 5}
	// 在索引2处插入3和4
	s = append(s[:2], append([]int{3, 4}, s[2:]...)...)
	fmt.Printf("插入后的切片: %v\n", s)

	// 切片作为函数参数
	modifySlice(s)
	fmt.Printf("函数修改后的切片: %v\n", s)

	// ==========================================
	// 映射 (Maps)
	// ==========================================

	// 声明map
	var _ map[string]int // nil map

	// 使用make创建map
	ages := make(map[string]int)

	// 使用字面量创建map
	population := map[string]int{
		"北京": 2170,
		"上海": 2418,
		"广州": 1510,
		"深圳": 1303,
	}

	// 添加或更新元素
	ages["张三"] = 25
	ages["李四"] = 30
	ages["王五"] = 35

	// 获取元素
	zhangSanAge := ages["张三"]
	fmt.Printf("张三的年龄: %d\n", zhangSanAge)

	// 检查键是否存在
	age, exists := ages["赵六"]
	if exists {
		fmt.Printf("赵六的年龄: %d\n", age)
	} else {
		fmt.Println("赵六不在map中")
	}

	// 删除元素
	delete(ages, "王五")
	fmt.Printf("删除王五后的ages: %v\n", ages)

	// 获取map的长度
	fmt.Printf("population的长度: %d\n", len(population))

	// 遍历map
	fmt.Println("\n遍历map:")
	for city, pop := range population {
		fmt.Printf("%s的人口: %d万\n", city, pop)
	}

	// 只遍历键
	fmt.Println("\n遍历map的键:")
	for city := range population {
		fmt.Println(city)
	}

	// 按键排序遍历
	fmt.Println("\n按键排序遍历map:")
	var cities []string
	for city := range population {
		cities = append(cities, city)
	}
	sort.Strings(cities)
	for _, city := range cities {
		fmt.Printf("%s的人口: %d万\n", city, population[city])
	}

	// map是引用类型
	populationCopy := population
	populationCopy["北京"] = 2200
	fmt.Printf("修改副本后的原map: %v\n", population) // 原map也会改变

	// map作为函数参数
	modifyMap(population)
	fmt.Printf("函数修改后的map: %v\n", population)

	// 使用map实现集合
	set := make(map[string]bool)
	set["苹果"] = true
	set["香蕉"] = true
	set["橙子"] = true

	// 检查元素是否在集合中
	fmt.Printf("苹果是否在集合中: %t\n", set["苹果"])
	fmt.Printf("葡萄是否在集合中: %t\n", set["葡萄"])

	// 嵌套map
	users := map[string]map[string]string{
		"user1": {
			"name":  "张三",
			"email": "zhangsan@example.com",
		},
		"user2": {
			"name":  "李四",
			"email": "lisi@example.com",
		},
	}

	fmt.Printf("\n用户信息:\n")
	for id, info := range users {
		fmt.Printf("ID: %s, 姓名: %s, 邮箱: %s\n", id, info["name"], info["email"])
	}

	// ==========================================
	// make和new函数
	// ==========================================

	// new函数分配内存，返回指向零值的指针
	ptr := new(int)
	*ptr = 42
	fmt.Printf("\nnew创建的int指针: %d\n", *ptr)

	// make函数创建slice、map或chan，并初始化
	s1 := make([]int, 5)       // 创建长度为5的切片
	m1 := make(map[string]int) // 创建map
	c1 := make(chan int, 10)   // 创建带缓冲的channel

	fmt.Printf("make创建的切片: %v\n", s1)
	fmt.Printf("make创建的map: %v\n", m1)
	fmt.Printf("make创建的channel容量: %d\n", cap(c1))

	// ==========================================
	// 练习
	// ==========================================

	// 1. 创建一个包含10个元素的整数数组，并计算所有元素的和

	// 2. 编写一个函数，接受一个整数切片，返回切片中的最大值和最小值

	// 3. 创建一个学生成绩map，键为学生姓名，值为分数，然后计算平均分

	// 4. 编写一个函数，接受两个切片，返回它们的交集（同时存在于两个切片中的元素）

	// 5. 使用嵌套map实现一个简单的图书管理系统，记录书名、作者、出版年份等信息
}

// 修改切片的函数
func modifySlice(s []int) {
	if len(s) > 0 {
		s[0] = 999
	}
}

// 修改map的函数
func modifyMap(m map[string]int) {
	m["深圳"] = 1350
}

// 打印切片信息的辅助函数
func printSliceInfo(name string, slice []int) {
	fmt.Printf("%s: 长度=%d 容量=%d %v\n", name, len(slice), cap(slice), slice)
}

// 格式化打印二维切片的辅助函数
func printMatrix(matrix [][]int) {
	for _, row := range matrix {
		fmt.Println(strings.Repeat("-", len(row)*3))
		for _, val := range row {
			fmt.Printf("| %d ", val)
		}
		fmt.Println("|")
	}
	fmt.Println(strings.Repeat("-", len(matrix[0])*3))
}
